void loop()
{
  //Obtenemos el valor base a partir del cual se encienden los leds
  int co2Threshold = mg811sensor.getThresholdLevel();

  //ANTIGUO int co2Value = mg811sensor.getPpm();

  //###########################################################
  char buffer[25]; 
  uint8_t ind =0;
  //Cozir sensors ship from the factory in streaming mode 
  //So we read incoming bytes into a buffer until we get '0x0A' which is the ASCII value for new-line 
  while(buffer[ind-1] != 0x0A) 
  { 
    if(cozirSerial.available()) 
    { 
      buffer[ind] = cozirSerial.read(); 
      ind++; 
    } 
  }
  DEBUG_PRINT(F("buffer cozir: "));
  DEBUG_PRINT(buffer);
  DEBUG_PRINTLN();
  int co2Value = cozirReport(buffer, ind); //Once we get the '0x0A' we will report what is in the buffer 


  //##########################################################


  String co2ValueStr = String(co2Value);
  if (co2Value == LOWER_THAN_MIN_PPM)
    co2ValueStr = "<" + String(MIN_MEASURABLE_CO2_LEVEL);
  else if (co2Value == HIGHER_THAN_MAX_PPM)
    co2ValueStr = ">" + String(MAX_MEASURABLE_CO2_LEVEL);

  //PRUEBA DEPURACIÓN
  double volts = mg811sensor.getMg811RawRead();  
  double mg811sensorVolts = volts / DC_GAIN;
  displayValues(volts, mg811sensorVolts, co2ValueStr); 
  //FIN PRUEBA DEPURACIÓN


  String co2ThresholdTxt = "CO2 max: " + String(co2Threshold) + "ppm";
  String co2ValueTxt = "CO2 act: " + co2ValueStr + "ppm";
  //String co2ValueTxt = String(mg811sensorVolts, 3) +  "V " + co2ValueStr + "ppm";
  lcd.displayText(co2ThresholdTxt, co2ValueTxt);



  //Ahora las comparaciones para las salidas
  //Escala de Avisos: salto en ppm para encender un led más
  const float sensitivity = (co2Threshold - 400) / 5;

  processLevels(co2Value, co2Threshold, sensitivity) ;

  //Un pequeño delay para no volver loco al puerto serie
  delay(LOOP_DELAY);

  // Reseteo del contador del watchdog timer para asegurarnos de que no se resetea el sistema si todo 
  // funciona como es debido. Si no se llama a esta función acabará por agotarse el tiempo de espera y
  //se reiniciará el arduino empezando de nuevo
  wdt_reset(); 
}


void processLevels(float co2Value, float co2Threshold, float sensitivity)
{
  if (co2Value > co2Threshold)
  {
    mg811sensor.setLedStatus(HIGH, HIGH, HIGH, HIGH, HIGH);    
    setAlarmState(true);
    setFanState(true);
    DEBUG_PRINT(F("Alarma y ventilador\n"));  
  }
  else if (co2Value >= (co2Threshold - sensitivity) && co2Value < co2Threshold)
  {
    mg811sensor.setLedStatus(HIGH, HIGH, HIGH, HIGH, LOW);  
    setAlarmState(false);
    setFanState(true);
    DEBUG_PRINT(F("Ventilador\n"));  
  }
  else if (co2Value >= (co2Threshold - 2 * sensitivity) && (co2Value < co2Threshold - sensitivity))
  {
    mg811sensor.setLedStatus(HIGH, HIGH, HIGH, LOW, LOW);
    setAlarmState(false);
    setFanState(true);
    DEBUG_PRINT(F("Ventilador\n"));  
  }
  else if ((co2Value >= (co2Threshold - 3 * sensitivity)) && (co2Value < co2Threshold - 2 * sensitivity))
  {
    mg811sensor.setLedStatus(HIGH, HIGH, LOW, LOW, LOW);
    setAlarmState(false);
    setFanState(false);
    DEBUG_PRINT(F("Nivel moderado CO2\n"));  
  }
  else if(co2Value < (co2Threshold -  3 * sensitivity))
  {
    mg811sensor.setLedStatus(HIGH, LOW, LOW, LOW, LOW);
    setAlarmState(false);
    setFanState(false);
    DEBUG_PRINT(F("Nivel bajo CO2\n"));  
  }
}

void displayValues(float volts, float mg811sensorVolts, String co2ValueStr)
{
  DEBUG_PRINT(F("Modulo:"));
  DEBUG_PRINT(String(volts, 5));
  DEBUG_PRINT( F("V | Sensor:"));
  DEBUG_PRINT(String(mg811sensorVolts, 5));
  DEBUG_PRINT( F("V\t" ));  

  DEBUG_PRINT(F("CO2 "));
  DEBUG_PRINT(co2ValueStr);
  DEBUG_PRINT( F("/"));  
  DEBUG_PRINT(mg811sensor.getThresholdLevel());
  DEBUG_PRINT(F(" ppm\n "));
}



int cozirReport(char* buffer, int ind)

{ 
  //Cycle through the buffer and send out each byte including the final linefeed 
  /* 
   each packet in the stream looks like "Z 00400 z 00360" 
   'Z' lets us know its a co2 reading. the first number is the filtered value 
   and the number after the 'z' is the raw value. 
   We are really only interested in the filtered value 
   */

  String val= ""; //holds the string of the value  

  boolean filteredReading = false;
  for(int i=0; i < ind+1; i++) 
  { 
    if(buffer[i] == 'z') //once we hit the 'z' we can stop 
      break; 
    if((buffer[i] != Z_CAPS_CHAR)&&(buffer[i] != BLANK_SPACE_CHAR)) //ignore 'Z' and white space 
    { 
      val += buffer[i] - 48; //because we break at 'z' the only bytes getting added are the numbers 
      // we subtract 48 to get to the actual numerical value 
      // example the character '9' has an ASCII value of 57. [57-48=9] 
      filteredReading = true;
    }
    if (filteredReading && (buffer[i] < 0x30 || buffer[i] > 0x39 ))  //si ya hemos encontrado el primer número, paramos cuando hay algo que no sean números 
      break;

  } 

  DEBUG_PRINT (F("val:"));
  DEBUG_PRINT (val);
  DEBUG_PRINTLN();

  double multiplier = 1; 
  // up to 2%  multiplier = 1 
  // up to 65% multiplier = 10 
  //up to 100% multiplier = 100; 
  int co2 = (multiplier * val.toInt()); //now we multiply the value by a factor specific ot the sensor. see theCozir software guide 
  Serial.print( "Co2 = "); 
  Serial.print(co2); 
  Serial.println(" ppm"); 
  return co2;
}





